/*
 * spcp.h
 *
 *  Created on: 2018年1月2日
 *      Author: xiaotao
 */

//simple_peripherals_communication_protocol

#ifndef SPCP_H_
#define SPCP_H_

#include "mytypes.h"

//二进制传输协议
//网络字节序
//将有效的数据，每个字节拆分成2个字节（前4位与后4位），TLV格式，帧头0xFF

/********************************************************/
//配置
#define SPCP_BUF_MIN_SET(X) (((X) + 6) * 2 - 1) //最小值 = （欲传输数据长度 + 6） * 2 -1
#define SPCP_WBUF_LEN SPCP_BUF_MIN_SET(150)
#define SPCP_RBUF_LEN SPCP_BUF_MIN_SET(150)

/********************************************************/

#define SPCP_HEADER_LEN (sizeof(spcp_t) - sizeof(void *))
#define SPCP_TAG 0xFF

#pragma pack(1)

typedef struct {
        uint8_t tag;
        uint8_t reserve; // 仅用于字节对齐
        uint16_t length;
        uint16_t crc16;
        void *val;
} spcp_t;

#pragma pack()

typedef ssize_t spcp_read_handler_t(int, void *, size_t, struct timeval *);
typedef ssize_t spcp_write_handler_t(int, const void *, size_t, struct timeval *);

typedef struct {
        spcp_write_handler_t *w_handler;
        spcp_read_handler_t *r_handler;
        int fd;
        uint8_t w_buf[SPCP_WBUF_LEN];
        uint8_t r_buf[SPCP_RBUF_LEN];
        uint8_t *w_ptr; // 如果数据长度大于SPCP_WBUF_LEN，则使用calloc的方法获取缓存
        uint8_t *r_ptr; // 同上
        struct timeval calloc_timeout;

        uint8_t r_buf4header[11]; // tag 1个字节，reserve 2个字节， length 4个字节, crc16 4个字节
        uint8_t r_fsm;
        uint16_t r_crc16;
        size_t r_buf_cur;
        size_t r_val_len;
        size_t r_buf_tot_size;
        bool is_r_buf_calloc;

} spcp_cache_t;

/*
 使用步骤:
 1.初始化 spcp_cache_t == {0}, 
 2.定义 spcp_cache_t--> w_handler/r_handler
 3.spcp_cache_t 交给代码维护，不允许代码修改
*/

ssize_t spcp_read_poll(spcp_cache_t *cache, void *buf, size_t count, struct timeval *timeout);
ssize_t spcp_write(spcp_cache_t *cache, const void *buf, size_t count, struct timeval *timeout);

#endif /* SPCP_H_ */